#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "wifi_manager.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "aliot_mqtt.h"
#include "esp_console.h"
#include "linenoise/linenoise.h"
#include "argtable3/argtable3.h"
#include "driver/uart.h"
#include "esp_vfs_dev.h"
#include "esp_system.h"
#include "cJSON.h"
#include "aliot.h"
#include "aliot_dm.h"
#include "driver/gpio.h"
#include "button.h"
#include "led_ws2812.h"
#include "esp_flash_partitions.h"
#include "esp_ota_ops.h"

#define TAG     "main"

#define EV_WIFI_CONNECTED_BIT           (1<<0)
#define EV_WIFI_DISCONNECTED_BIT        (1<<1)
static EventGroupHandle_t s_wifi_ev;

#define LED_GPIO        GPIO_NUM_27
#define BUTTON_GPIO     GPIO_NUM_39
#define WS2812_GPIO     GPIO_NUM_26
#define WS2812_NUM      12

//led灯的状态
static int led_level = 0;

//ws2812操作句柄
static ws2812_strip_handle_t    ws2812_handle = NULL;

/**
 * wifi事件回调函数
 * @param ev wifi事件
 * @param data 参数，暂无用处
 * @return 无
 */
void wifi_callback(wifi_ev_t ev, void *data)
{
    if(ev == WIFI_EV_SNTP)
    {
        xEventGroupSetBits(s_wifi_ev,EV_WIFI_CONNECTED_BIT);
    }
    if(ev == WIFI_EV_DISCONNECTED)
    {
        xEventGroupSetBits(s_wifi_ev,EV_WIFI_DISCONNECTED_BIT);
    }
    if(ev == WIFI_EV_READY)
    {
        wifi_manager_start();
    }
}

static EventGroupHandle_t   s_button_event = NULL;
#define SHORT_EV    (BIT0)

//短按回调函数
void btn_short_press(void)
{
    xEventGroupSetBits(s_button_event,SHORT_EV);
}
void button_task(void* param)
{
    //按键配置结构体
    button_config_t button_cfg =
    {
        .gpio_num = BUTTON_GPIO,           //gpio号
        .active_level = 0,       //按下的电平
        .long_press_time = 3000,    //长按时间
        .short_cb = btn_short_press,   //短按回调函数
        .long_cb = NULL,    //长按回调函数
    };
    s_button_event = xEventGroupCreate();
    button_event_set(&button_cfg);

    gpio_config_t led_gpio = 
    {
        .intr_type = GPIO_INTR_DISABLE,
        .mode = GPIO_MODE_OUTPUT,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pin_bit_mask = (1ull<<LED_GPIO)
    };
    gpio_config(&led_gpio);
    EventBits_t ev;
    while(1)
    {
        ev = xEventGroupWaitBits(s_button_event,SHORT_EV,pdTRUE,pdFALSE,pdMS_TO_TICKS(5000));
        if(ev & SHORT_EV)
        {
            led_level = led_level?0:1;
            gpio_set_level(LED_GPIO,led_level);
            aliot_post_property_int("LightSwitch",led_level);
        }
    }
}

/**
 * 板级初始化，自己在这个函数加初始化代码
 * @param 无
 * @return 无
 */
void board_init(void)
{
    esp_err_t ret_val = ESP_OK;
    ret_val = nvs_flash_init();
    if (ret_val == ESP_ERR_NVS_NO_FREE_PAGES || ret_val == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret_val = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret_val );
}


/**
 * 当后台下发了属性值时，会调用此回调函数
 * @param name 属性值的名字
 * @param value 属性值
 * @return 无
 */
void  aliot_property_cb(const char* name,cJSON* value_js)
{
    if(strcmp(name,"LightSwitch") == 0)
    {
        int value = cJSON_GetNumberValue(value_js);
        led_level = value;
        ESP_LOGI(TAG,"aliot set property->name:%s,value:%i",name,value);
        gpio_set_level(LED_GPIO,led_level);
    }
    else if(strcmp(name,"RGBColor") == 0)
    {
        int red,green,blue;
        red = cJSON_GetNumberValue(cJSON_GetObjectItem(value_js,"Red"));
        green = cJSON_GetNumberValue(cJSON_GetObjectItem(value_js,"Green"));
        blue = cJSON_GetNumberValue(cJSON_GetObjectItem(value_js,"Blue"));
        ESP_LOGI(TAG,"aliot set property->name:%s,red:%i,green:%i,blue:%i",name,red,green,blue);
        for(int i = 0;i < WS2812_NUM;i++)
        {
            ws2812_write(ws2812_handle,i,red,green,blue);
        }
    }
}


void app_main(void) 
{
    
    //板级初始化
    board_init();

    //wifi初始化
    s_wifi_ev = xEventGroupCreate();
    wifi_manager_init(wifi_callback);
    aliot_set_property_cb(aliot_property_cb);
    //初始化BUTTON和LED
    xTaskCreatePinnedToCore(button_task,"button",4096,NULL,2,NULL,1);

    ws2812_init(WS2812_GPIO,WS2812_NUM,&ws2812_handle);
    ESP_LOGI(TAG,"this is aliot version %s,just for test!",get_app_version());
    while(1)
    {
        //这里等待一个WIFI连接成功的事件，然后再启动aliot连接
        EventBits_t bits = xEventGroupWaitBits(s_wifi_ev,EV_WIFI_CONNECTED_BIT,pdTRUE,pdFALSE,pdMS_TO_TICKS(5000));
        if(bits&EV_WIFI_CONNECTED_BIT)
        {
            aliot_start();
            break;
        }
    }
    
    while(1)
    {
        //do yourself thing
        vTaskDelay(pdMS_TO_TICKS(1*1000));
    }
}
